#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
快速解析脚本 - 简化版
用于快速将Excel文件转换为JSON
"""

import pandas as pd
import json
import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox
import math


class NaNEncoder(json.JSONEncoder):
    """自定义JSON编码器，将NaN/inf转换为null"""
    def encode(self, obj):
        if isinstance(obj, float):
            if math.isnan(obj) or math.isinf(obj):
                return 'null'
        return super().encode(obj)
    
    def iterencode(self, obj, _one_shot=False):
        """处理嵌套的NaN值"""
        for chunk in super().iterencode(obj, _one_shot):
            # 替换NaN和Infinity为null
            chunk = chunk.replace('NaN', 'null')
            chunk = chunk.replace('Infinity', 'null')
            chunk = chunk.replace('-Infinity', 'null')
            yield chunk


def quick_parse(excel_path, output_path=None):
    """
    快速解析Excel文件为JSON
    
    Args:
        excel_path: Excel文件路径
        output_path: 输出JSON文件路径（可选）
    """
    try:
        print(f"正在读取: {excel_path}")
        
        # 读取Excel文件（自动处理所有工作表）
        excel_file = pd.ExcelFile(excel_path, engine='openpyxl')
        
        result = {
            "fileName": os.path.basename(excel_path),
            "sheets": {}
        }
        
        # 遍历所有工作表
        for sheet_name in excel_file.sheet_names:
            print(f"  - 解析工作表: {sheet_name}")
            
            # 读取工作表
            df = pd.read_excel(excel_file, sheet_name=sheet_name, engine='openpyxl')
            
            # 删除空行和空列
            df = df.dropna(how='all').dropna(axis=1, how='all')
            
            # 替换NaN、inf等特殊值为None（在JSON中会变成null）
            df = df.replace({
                pd.NA: None,
                pd.NaT: None,
                float('nan'): None,
                float('inf'): None,
                float('-inf'): None
            })
            
            # 转换为字典
            result["sheets"][sheet_name] = {
                "columns": df.columns.tolist(),
                "rowCount": len(df),
                "data": df.to_dict(orient='records')
            }
            
            print(f"    完成! 共 {len(df)} 行, {len(df.columns)} 列")
        
        # 确定输出路径
        if output_path is None:
            base_name = os.path.splitext(os.path.basename(excel_path))[0]
            output_path = f"{base_name}.json"
        
        # 保存JSON文件（使用自定义编码器处理NaN值）
        with open(output_path, 'w', encoding='utf-8') as f:
            json.dump(result, f, ensure_ascii=False, indent=2, cls=NaNEncoder)
        
        print(f"\n✓ 成功! JSON文件已保存至: {output_path}")
        print(f"  - 总工作表数: {len(result['sheets'])}")
        
        return output_path
        
    except Exception as e:
        print(f"\n✗ 错误: {e}")
        import traceback
        traceback.print_exc()
        return None


def select_file_gui():
    """
    使用GUI选择Excel文件
    """
    # 创建隐藏的主窗口
    root = tk.Tk()
    root.withdraw()
    root.attributes('-topmost', True)
    
    # 弹出文件选择对话框
    excel_file = filedialog.askopenfilename(
        title="请选择Excel文件",
        filetypes=[
            ("Excel文件", "*.xlsx *.xls"),
            ("所有文件", "*.*")
        ],
        initialdir=os.getcwd()
    )
    
    root.destroy()
    return excel_file


if __name__ == "__main__":
    # 使用GUI选择文件
    print("请在弹出的对话框中选择Excel文件...")
    excel_file = select_file_gui()
    
    if not excel_file:
        print("未选择文件，程序退出。")
        sys.exit(0)
    
    print(f"已选择文件: {excel_file}")
    
    # 设置输出文件名（同时输出到两个位置）
    output_file1 = "output/personnel_portrait.json"
    output_file2 = "web/public/data/personnel_portrait.json"
    
    # 确保输出目录存在
    for output_file in [output_file1, output_file2]:
        output_dir = os.path.dirname(output_file)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir)
            print(f"创建目录: {output_dir}")
    
    # 执行解析（生成到两个位置）
    result1 = quick_parse(excel_file, output_file1)
    result2 = quick_parse(excel_file, output_file2)
    
    # 显示完成提示
    if result1 and result2:
        root = tk.Tk()
        root.withdraw()
        root.attributes('-topmost', True)
        messagebox.showinfo(
            "解析完成", 
            f"JSON文件已生成！\n\n保存位置：\n1. {os.path.abspath(output_file1)}\n2. {os.path.abspath(output_file2)}\n\n前端可直接访问！"
        )
        root.destroy()

